import { Agent } from '@mastra/core/agent';
import { LibSQLStore } from '@mastra/libsql';
import { Memory } from '@mastra/memory';
import { caseGenerationTool } from '../tools/case-generation.tool';
import { CaseGenerationRequestSchema } from '../types/game';
import { createModel } from '../provider/model';
/**
 * 案件生成Agent
 * 负责根据难度和主题生成完整的推理案件
 * 包括案件背景、嫌疑人信息和初始线索
 * 包括案件背景、嫌疑人信息和初始线索
 */
export const caseGeneratorAgent = new Agent({
  name: 'case-generator',
  instructions: `
    你是一个专业的推理案件生成专家。你的任务是使用工具来生成结构化的案件数据。

    **关键指令：你必须调用 caseGenerationTool 工具，不要只提供文本回应！**


    你是一个专业的推理小说作家和案件设计师，专门创作极简但精彩的推理案件。
    
    ## 核心职责
    1. 根据指定难度生成逻辑严密的推理案件
    2. 创造具有独特人格的嫌疑人角色
    3. 设计层次分明的线索系统
    4. 确保案件在3-15分钟内可以调查完毕
    
    ## 创作原则
    
    ### 案件设计
    - **简洁性**: 案件背景要简洁明了，避免过于复杂的情节
    - **逻辑性**: 所有线索和证据必须符合逻辑，避免矛盾
    - **可解性**: 确保有足够的线索指向真凶，但不能过于明显
    - **趣味性**: 案件要有吸引力，能够激发玩家的推理兴趣
    
    ### 嫌疑人设计
    - 每个嫌疑人都要有独特的人格特征和背景故事
    - 所有嫌疑人都要有合理的作案动机和不在场证明
    - 真凶的设计要巧妙，不能过于明显也不能完全无迹可寻
    - 红鲱鱼嫌疑人要有足够的可疑点来误导玩家
    
    ### 线索系统
    - 线索要有层次性：明显线索、隐藏线索、关键线索
    - 每条线索都要与特定嫌疑人相关联
    - 重要线索需要通过深入调查才能发现
    - 避免线索过于直接或过于隐晦
    
    ## 难度分级
    
    ### Easy (简单)
    - 线索明显，逻辑链条简单
    - 真凶的可疑行为较为明显
    - 动机简单直接
    - 适合新手玩家
    
    ### Normal (普通)
    - 需要一定的推理能力
    - 包含红鲱鱼线索来增加难度
    - 真凶有一定的伪装
    - 动机相对复杂
    
    ### Hard (困难)
    - 复杂的动机和关系网
    - 多重伪装和误导
    - 需要仔细分析才能发现真相
    - 适合有经验的推理爱好者
    
    ## 案件类型参考
    - 密室杀人：利用环境特点制造不可能犯罪
    - 毒杀案件：使用毒物，重点在于投毒时机和方式
    - 意外伪装：将谋杀伪装成意外事故
    - 时间陷阱：利用时间差制造不在场证明
    - 身份调换：利用身份混淆来掩盖真相
    
    ## 输出要求
    **重要：你必须使用 caseGenerationTool 工具来生成案件数据，不要只提供文本描述。**

    当收到案件生成请求时：
    1. 立即调用 caseGenerationTool 工具
    2. 传入正确的参数：difficulty, theme, suspectCount
    3. 不要生成文本描述，让工具来创建结构化数据

    确保生成的内容符合指定的难度要求，并且所有信息都是逻辑自洽的。

    记住：你的目标是创造一个既有挑战性又公平的推理游戏体验。
  `,
  model: createModel(),
  tools: { caseGenerationTool },
  memory: new Memory({
    storage: new LibSQLStore({
      url: 'file:../mastra.db',
    }),
  }),
});

/**
 * 生成案件的便捷方法
 * @param difficulty 案件难度
 * @param theme 案件主题（可选）
 * @param suspectCount 嫌疑人数量
 * @returns 生成的案件数据
 */
export async function generateCase(
  difficulty: 'easy' | 'normal' | 'hard',
  theme?: string,
  suspectCount: number = 3
) {
  try {
    console.log(`开始生成案件 - 难度: ${difficulty}, 主题: ${theme || '无'}, 嫌疑人数量: ${suspectCount}`);

    // 验证输入参数
    const validatedInput = CaseGenerationRequestSchema.parse({
      difficulty,
      theme,
      suspectCount
    });

    // 构建提示词 - 强制要求使用工具
    const prompt = `立即使用 caseGenerationTool 工具生成案件数据！

参数：
- difficulty: "${difficulty}"
- theme: "${theme || '随机'}"
- suspectCount: ${suspectCount}

不要提供文本描述，直接调用工具！工具会生成完整的结构化案件数据。`;

    console.log('发送提示词给AI Agent:', prompt);

    // 调用Agent生成案件，添加超时和重试机制
    let response: any;
    let retryCount = 0;
    const maxRetries = 3;

    while (retryCount < maxRetries) {
      try {
        response = await Promise.race([
          caseGeneratorAgent.streamVNext([
            {
              role: 'user',
              content: prompt,
            },
          ]),
          new Promise((_, reject) =>
            setTimeout(() => reject(new Error('Agent调用超时')), 30000)
          )
        ]);
        break; // 成功则跳出循环
      } catch (error) {
        retryCount++;
        const errorMessage = error instanceof Error ? error.message : String(error);
        console.log(`Agent调用失败，重试 ${retryCount}/${maxRetries}:`, errorMessage);

        if (retryCount >= maxRetries) {
          throw new Error(`Agent调用失败，已重试${maxRetries}次: ${errorMessage}`);
        }

        // 等待一段时间后重试
        await new Promise(resolve => setTimeout(resolve, 2000 * retryCount));
      }
    }

    // 处理流式响应
    let result = '';
    for await (const chunk of response.textStream) {
      result += chunk;
    }

    console.log('AI Agent文本响应:', result);

    // 等待工具调用完成
    const toolCalls = await response.toolCalls;
    console.log('工具调用数量:', toolCalls?.length || 0);

    // 从工具调用结果中提取案件数据 - 使用新版本API结构
    const toolResults = await response.toolResults;
    if (toolResults && toolResults.length > 0) {
      console.log('工具调用详情:', JSON.stringify(toolResults[0], null, 2));
      const toolResult = toolResults[0];

      if (toolResult.payload?.result) {
        const caseData = toolResult.payload.result;

        // 验证案件数据
        const validation = validateCaseData(caseData);
        if (!validation.isValid) {
          console.warn('生成的案件数据验证失败:', validation.errors);
          // 继续使用数据，但记录警告
        }

        console.log('案件生成成功');
        return caseData;
      } else {
        console.error('工具结果中没有payload.result');
        console.log('工具结果结构:', JSON.stringify(toolResult, null, 2));
      }
    }

    console.error('AI Agent未返回工具调用结果');
    throw new Error('案件生成失败：未能获取有效的工具调用结果');

  } catch (error) {
    console.error('案件生成错误:', error);

    // 如果是工具调用失败，使用内置降级方案
    if (error instanceof Error && error.message.includes('工具调用结果')) {
      console.log('使用内置降级方案生成案件');
      try {
        const fallbackCase = generateFallbackCase(difficulty, theme, suspectCount);
        console.log('降级方案成功生成案件');
        return fallbackCase;
      } catch (fallbackError) {
        console.error('降级方案也失败了:', fallbackError);
      }
    }

    throw new Error(`案件生成失败: ${error instanceof Error ? error.message : '未知错误'}`);
  }
}

/**
 * 验证案件数据的完整性
 * @param caseData 案件数据
 * @returns 验证结果
 */
export function validateCaseData(caseData: any): {
  isValid: boolean;
  errors: string[];
} {
  const errors: string[] = [];
  
  // 检查基本案件信息
  if (!caseData.case) {
    errors.push('缺少案件基本信息');
  } else {
    if (!caseData.case.title) errors.push('缺少案件标题');
    if (!caseData.case.description) errors.push('缺少案件描述');
    if (!caseData.case.culpritId) errors.push('缺少真凶ID');
  }
  
  // 检查嫌疑人信息
  if (!caseData.suspects || !Array.isArray(caseData.suspects)) {
    errors.push('缺少嫌疑人信息');
  } else {
    if (caseData.suspects.length < 2) {
      errors.push('嫌疑人数量不足（至少需要2个）');
    }
    
    // 检查是否有真凶
    const hasCulprit = caseData.suspects.some((suspect: any) => suspect.isCulprit);
    if (!hasCulprit) {
      errors.push('没有指定真凶');
    }
    
    // 检查真凶ID是否匹配
    const culprit = caseData.suspects.find((suspect: any) => suspect.id === caseData.case.culpritId);
    if (!culprit) {
      errors.push('真凶ID与嫌疑人列表不匹配');
    }
  }
  
  // 检查线索信息
  if (!caseData.initialClues || !Array.isArray(caseData.initialClues)) {
    errors.push('缺少初始线索');
  } else {
    if (caseData.initialClues.length === 0) {
      errors.push('没有初始线索');
    }
  }
  
  return {
    isValid: errors.length === 0,
    errors
  };
}

/**
 * 生成降级案件数据
 * 当AI Agent失败时使用的备用方案
 */
function generateFallbackCase(
  difficulty: 'easy' | 'normal' | 'hard',
  theme?: string,
  suspectCount: number = 3
) {
  const caseId = `case-${Date.now()}`;
  const finalTheme = theme || '办公室';

  return {
    case: {
      id: caseId,
      title: `${finalTheme}谋杀案`,
      description: `在${finalTheme}发生了一起神秘的谋杀案，需要你来调查真相。`,
      location: finalTheme,
      timeOfCrime: '上午10:30',
      victim: '张先生',
      murderWeapon: '未知',
      motive: '待查明',
      culpritId: 'suspect-1',
      difficulty,
      createdAt: new Date().toISOString()
    },
    suspects: Array.from({ length: suspectCount }, (_, i) => ({
      id: `suspect-${i + 1}`,
      name: `嫌疑人${i + 1}`,
      personality: ['谨慎内向', '野心勃勃', '老实本分', '机警敏锐'][i] || '普通性格',
      background: ['新入职员工', '竞争对手', '长期员工', '外包人员'][i] || '普通背景',
      alibi: '声称有不在场证明',
      suspicionLevel: Math.floor(Math.random() * 10) + 1,
      isCulprit: i === 0 // 第一个嫌疑人是真凶
    })),
    initialClues: [
      {
        id: 'clue-1',
        caseId,
        description: '现场发现的可疑物品',
        type: 'physical',
        importance: 5,
        isRevealed: true,
        relatedSuspects: ['suspect-1']
      },
      {
        id: 'clue-2',
        caseId,
        description: '监控录像显示的异常行为',
        type: 'witness',
        importance: 4,
        isRevealed: true,
        relatedSuspects: ['suspect-2']
      }
    ]
  };
}

/**
 * 获取案件统计信息
 * @param caseData 案件数据
 * @returns 统计信息
 */
export function getCaseStatistics(caseData: any) {
  if (!caseData) return null;
  
  return {
    suspectCount: caseData.suspects?.length || 0,
    clueCount: caseData.initialClues?.length || 0,
    difficulty: caseData.case?.difficulty || 'unknown',
    revealedClues: caseData.initialClues?.filter((clue: any) => clue.isRevealed).length || 0,
    hiddenClues: caseData.initialClues?.filter((clue: any) => !clue.isRevealed).length || 0,
    culpritName: caseData.suspects?.find((suspect: any) => suspect.isCulprit)?.name || 'Unknown'
  };
}